package com.luoyang.controller;

import cn.hutool.core.date.StopWatch;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.luoyang.domain.BusRegionCoreEntity;
import com.luoyang.mapper.BusRegionMapper;
import lombok.extern.slf4j.Slf4j;
import org.geotools.data.DataUtilities;
import org.geotools.data.collection.ListFeatureCollection;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.feature.DefaultFeatureCollection;
import org.geotools.feature.SchemaException;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.geojson.feature.FeatureJSON;
import org.geotools.geometry.jts.JTS;
import org.geotools.geometry.jts.JTSFactoryFinder;
import org.geotools.referencing.CRS;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.LineString;
import org.locationtech.jts.geom.Point;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
@RestController
@RequestMapping("/busRegion")
public class BusRegionController {

    @Autowired
    private BusRegionMapper busRegionMapper;

    @GetMapping("/list")
    public Object list() throws FactoryException, SchemaException, IOException {
        StopWatch stopWatch = new StopWatch();

        stopWatch.start("busRegionCoreEntities");
        List<BusRegionCoreEntity> busRegionCoreEntities = busRegionMapper.selectList(new LambdaQueryWrapper<>());
        stopWatch.stop();

        stopWatch.start("transform");
        CoordinateReferenceSystem sourceCRS = CRS.decode("EPSG:4525");
        CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:4326");
        MathTransform mathTransform = CRS.findMathTransform(sourceCRS, targetCRS, true);
        stopWatch.stop();

        stopWatch.start("features");
        List<BusRegionCoreEntity> tmp = busRegionCoreEntities.subList(0, 1);
        DefaultFeatureCollection collection = new DefaultFeatureCollection("features");
        tmp.forEach(busRegionCoreEntity -> {
            try {
                Coordinate c1 = new Coordinate(busRegionCoreEntity.getStartY().doubleValue(), busRegionCoreEntity.getStartX().doubleValue());
                Coordinate c2 = new Coordinate(busRegionCoreEntity.getEndY().doubleValue(), busRegionCoreEntity.getEndX().doubleValue());

                GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();

                Coordinate d1 = JTS.transform(c1, new Coordinate(), mathTransform);
                Coordinate d2 = JTS.transform(c2, new Coordinate(), mathTransform);

                Coordinate r1 = new Coordinate(d1.getY(), d1.getX());
                Coordinate r2 = new Coordinate(d2.getY(), d2.getX());

                Coordinate[] coordinates = new Coordinate[]{r1, r2};
                LineString lineString = geometryFactory.createLineString(coordinates);

                SimpleFeatureType type = DataUtilities.createType("Link", "geometry:" + lineString.getGeometryType() + ",regionName:String,startPoint:String,endPoint:String");
                SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(type);
                featureBuilder.add(lineString);
                featureBuilder.add(busRegionCoreEntity.getRegionName());
                featureBuilder.add("[" + busRegionCoreEntity.getStartX() + "," + busRegionCoreEntity.getStartY() + "]");
                featureBuilder.add("[" + busRegionCoreEntity.getEndX() + "," + busRegionCoreEntity.getEndY() + "]");
                SimpleFeature feature = featureBuilder.buildFeature(String.valueOf(busRegionCoreEntity.getId()));
                collection.add(feature);

            } catch (TransformException | SchemaException e) {
                throw new RuntimeException(e);
            }
        });
        stopWatch.stop();

        stopWatch.start("collection");
        StringWriter writer = new StringWriter();
        FeatureJSON fJson = new FeatureJSON();
        fJson.writeFeatureCollection(collection, writer);
        stopWatch.stop();
        log.info(stopWatch.prettyPrint(TimeUnit.MILLISECONDS));

        return writer.toString();
    }

}
